/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.dashboard;

import java.util.List;
import org.netbeans.api.dashboard.DashboardManager;
import org.netbeans.api.settings.ConvertAsProperties;
import org.netbeans.spi.dashboard.DashboardDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.OnShowing;
import org.openide.windows.WindowManager;
import org.openide.windows.WindowSystemEvent;
import org.openide.windows.WindowSystemListener;

/**
 * Default Dashboard Displayer top component.
 */
@ConvertAsProperties(
        dtd = "-//org.netbeans.modules.dashboard//Dashboard//EN",
        autostore = false
)
@TopComponent.Description(
        preferredID = "DashboardDisplayer",
        persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED
)
@TopComponent.Registration(mode = "editor", openAtStartup = false, position = 0)
@Messages({
    "CTL_DashboardTopComponent=Dashboard",
    "HINT_DashboardTopComponent=The Dashboard window"
})
public final class DashboardTopComponent extends TopComponent {

    private static final String ID = "DashboardDisplayer";

    private List<DashboardDisplayer.WidgetReference> widgetRefs;
    private DashboardPanel dashboardPanel;

    public DashboardTopComponent() {
        initComponents();
        scrollPane.getVerticalScrollBar().setUnitIncrement(20);
        setName(Bundle.CTL_DashboardTopComponent());
        setToolTipText(Bundle.HINT_DashboardTopComponent());
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scrollPane = new javax.swing.JScrollPane();
        dashContainer = new javax.swing.JPanel();
        emptyLabel = new javax.swing.JLabel();

        setLayout(new java.awt.BorderLayout());

        scrollPane.setBorder(null);
        scrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setViewportBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));

        dashContainer.setLayout(new java.awt.GridBagLayout());

        org.openide.awt.Mnemonics.setLocalizedText(emptyLabel, org.openide.util.NbBundle.getMessage(DashboardTopComponent.class, "DashboardTopComponent.emptyLabel.text")); // NOI18N
        dashContainer.add(emptyLabel, new java.awt.GridBagConstraints());

        scrollPane.setViewportView(dashContainer);

        add(scrollPane, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel dashContainer;
    private javax.swing.JLabel emptyLabel;
    private javax.swing.JScrollPane scrollPane;
    // End of variables declaration//GEN-END:variables
    @Override
    public void componentShowing() {
        if (dashboardPanel != null) {
            dashboardPanel.notifyShowing();
        }
    }

    @Override
    public void componentHidden() {
        if (dashboardPanel != null) {
            dashboardPanel.notifyHidden();
        }
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0"); //NOI18N
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }

    private void installWidgets(DefaultDashboardDisplayer displayer,
            List<DashboardDisplayer.WidgetReference> widgetRefs) {
        if (this.widgetRefs != null) {
            if (this.widgetRefs.equals(widgetRefs)) {
                return;
            }
        }
        this.widgetRefs = List.copyOf(widgetRefs);
        // TODO allow panel to be reconfigured at runtime, and detach removed widgets
        this.dashboardPanel = new DashboardPanel(displayer, widgetRefs);
        dashContainer.removeAll();
        dashContainer.add(this.dashboardPanel);
        dashboardPanel.notifyShowing();
    }

    static void show(DefaultDashboardDisplayer displayer,
            List<DashboardDisplayer.WidgetReference> widgetRefs) {
        DashboardTopComponent dashTC = find();
        if (dashTC == null) {
            return;
        }
        if (widgetRefs.isEmpty()) {
            dashTC.close();
            return;
        }
        dashTC.installWidgets(displayer, widgetRefs);
        if (!dashTC.isOpened()) {
            dashTC.openAtTabPosition(0);
        }
        dashTC.requestActive();
    }

    private static DashboardTopComponent find() {
        TopComponent tc = WindowManager.getDefault().findTopComponent(ID);
        if (tc instanceof DashboardTopComponent dashTC) {
            return dashTC;
        } else {
            return null;
        }
    }

    @OnShowing
    public static final class Startup implements Runnable {

        @Override
        public void run() {
            if (DefaultDashboardDisplayer.isDefaultDisplayer()
                    && isShowOnStartup()) {
                WindowManager.getDefault().invokeWhenUIReady(() -> {
                    DashboardManager.getDefault().show();
                });
            } else {
                DashboardTopComponent tc = find();
                if (tc != null && tc.isOpened()) {
                    tc.close();
                }
            }
            WindowManager.getDefault().addWindowSystemListener(new WindowSystemListener() {
                @Override
                public void afterLoad(WindowSystemEvent event) {
                }

                @Override
                public void afterSave(WindowSystemEvent event) {
                }

                @Override
                public void beforeLoad(WindowSystemEvent event) {
                }

                @Override
                public void beforeSave(WindowSystemEvent event) {
                    WindowManager.getDefault().removeWindowSystemListener(this);
                    DashboardTopComponent tc = find();
                    if (DefaultDashboardDisplayer.isDefaultDisplayer()
                            && isShowOnStartup()) {
                        if (tc != null) {
                            tc.open();
                            tc.requestActive();
                        }
                    } else {
                        if (tc != null) {
                            tc.close();
                        }
                    }
                }
            });
        }

        private boolean isShowOnStartup() {
            FileObject config = FileUtil.getConfigFile("Dashboard/Main");
            if (config == null) {
                return false;
            }
            return Boolean.TRUE.equals(config.getAttribute("showOnStartup"));
        }

    }

}
